package cn.openea.perpartner.evaluation.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.openea.perpartner.common.core.exception.ServiceException;
import cn.openea.perpartner.common.core.text.Convert;
import cn.openea.perpartner.common.core.utils.IdWorker;
import cn.openea.perpartner.common.core.web.domain.AjaxResult;
import cn.openea.perpartner.evaluation.web.entity.vo.EvaluationTaskVo;
import cn.openea.perpartner.evaluation.web.service.ISendMsgService;
import cn.openea.perpartner.meily.behavioral.entity.BehavioralData;
import cn.openea.perpartner.meily.behavioral.service.IBehavioralDataService;
import cn.openea.perpartner.evaluation.web.entity.EvaluationSignup;
import cn.openea.perpartner.evaluation.web.service.IEvaluationSignupService;
import cn.openea.perpartner.meily.web.entity.*;
import cn.openea.perpartner.evaluation.web.entity.EvaluationTask;
import cn.openea.perpartner.evaluation.web.mapper.EvaluationTaskMapper;
import cn.openea.perpartner.evaluation.web.service.IEvaluationTaskService;
import cn.openea.perpartner.meily.web.service.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author rains
 * @since 2023-07-05 14:21
 */
@Slf4j
@Service("evaluationTaskService")
public class EvaluationTaskServiceImpl extends ServiceImpl<EvaluationTaskMapper, EvaluationTask> implements IEvaluationTaskService {

    @Resource
    private IGoodsService goodsService;
    @Resource
    private ITaskHallService taskHallService;
    @Resource
    private IBehavioralDataService behavioralDataService;
    @Resource
    private IGoodsBusinessService goodsBusinessService;
    @Resource
    private IEvaluationSignupService evaluationSignupService;
    @Resource
    private ITodoService todoService;
    @Resource
    private ISendMsgService sendMsgService;
    private IdWorker worker = new IdWorker(1, 1, 1);


    @Value("${sso.url}")
    private String ssoUri;
    @Resource
    private IEvaluationService evaluationService;

    /**
     * 发布测评任务
     * 1.保存测评记录
     * 2.保存到需求大厅（上架）
     * 3.汇集数据
     * 4.保存一条当前商品记录到meily_goods_business表，用于查询
     * @param evaluationTask 实例对象
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult publish(@NonNull EvaluationTask evaluationTask) {

        // 任务单号，全使用数字
        evaluationTask.setTaskNumber(String.valueOf(worker.nextId()));

        // 剩余名额
        evaluationTask.setRemainQuota(evaluationTask.getQuota());

        // 校验商品
        Goods goods = Optional.ofNullable(goodsService.findById(evaluationTask.getGoodsId()))
                .orElseThrow(() -> new ServiceException("商品不存在"));
        if (!"已上架".equals(goods.getStatus())) {
            throw new ServiceException("商品还未上架");
        }
        // 获取商品信息
        evaluationTask.setGoodsNo(goods.getGoodsNo());
        evaluationTask.setGoodsName(goods.getGoodsName());
        evaluationTask.setGoodsImages(goods.getGoodsImages());
        evaluationTask.setGoodsTag(goods.getGoodsTag());
        evaluationTask.setSpecification(goods.getSpecification());
        if (StrUtil.isBlank(evaluationTask.getSceneAssetsId())){
            evaluationTask.setSceneAssetsId(goods.getSceneAssetsId());
        }
        if (StrUtil.isBlank(evaluationTask.getSceneId())){
            evaluationTask.setSceneId(goods.getSceneId());
        }

        // 企业编号
        if (StrUtil.isBlank(evaluationTask.getEnterpriseNo())){
            evaluationTask.setEnterpriseNo(goods.getEnterpriseNo());
        }

        // 企业名称
        if (StrUtil.isBlank(evaluationTask.getEnterpriseName())){
            evaluationTask.setEnterpriseName(goods.getEnterpriseName());
        }

        if("0".equals(evaluationTask.getEnableRating())){
            // 不开启评级，以下字段需要置空
            evaluationTask.setRatingTime("");// 评级时间
            evaluationTask.setRatingMemberId(""); // 评级人员id
            evaluationTask.setRatingMemberName(""); // 评级人员id
        }

        // 1.发布测评任务（保存测评记录）
        if (baseMapper.insert(evaluationTask) < 0) {
            return AjaxResult.error("保存测评详情出错了！");
        }

        // 商品图
        String imageUrl = evaluationTask.getMainPicture();
        if(StrUtil.isNotBlank(imageUrl)){
            imageUrl += "," + goods.getGoodsImages();
        } else {
            imageUrl = goods.getGoodsImages();
        }

        // 价格
        String price = "0";
        BigDecimal minPrice = null;
        BigDecimal maxPrice = null;

        // 是否评级发放报酬。0:否；1:是；默认1
        if("1".equals(evaluationTask.getEnableRating())){

            BigDecimal[] rewards = {evaluationTask.getLevelAReward(), evaluationTask.getLevelBReward(), evaluationTask.getLevelCReward()};
            Arrays.sort(rewards);

            for (BigDecimal number : rewards) {
                if (number.compareTo(BigDecimal.ZERO) > 0) {
                    if (minPrice == null) {
                        minPrice = number;
                    }
                    maxPrice = number;
                }
            }
            if (minPrice != null && maxPrice != null) {
                if(maxPrice.compareTo(minPrice) > 0 ){
                    price = minPrice + " ~ " + maxPrice;
                } else if(maxPrice.compareTo(minPrice) == 0 ){
                    price = maxPrice.toString();
                }
            }
        } else {
            // 不需要评级直接发放报酬
            price = evaluationTask.getReward().toString();
            minPrice = evaluationTask.getReward();
            maxPrice = evaluationTask.getReward();
        }

        // 默认不公开
        String taskState = "需求下架";
        String taskStatus = "下架";

        // 公开活动
        if("1".equals(evaluationTask.getOpen())){
            taskState = "火热报名";
            taskStatus = "上架";
        }

        // 优惠券金额
        String couponLabel = "";

        // 是否评级发放报酬。0:否；1:是；默认1
        if("1".equals(evaluationTask.getEnableRating())) {
            BigDecimal[] couponAmounts = {evaluationTask.getLevelACouponAmount(), evaluationTask.getLevelBCouponAmount(), evaluationTask.getLevelCCouponAmount()};
            Arrays.sort(couponAmounts);
            BigDecimal amount = couponAmounts[couponAmounts.length - 1];

            if (amount != null && amount.compareTo(BigDecimal.ZERO) > 0) {
                couponLabel = "最高获" + amount + "元优惠券";
            }
        } else {
            if (evaluationTask.getCouponAmount() != null && evaluationTask.getCouponAmount().compareTo(BigDecimal.ZERO) > 0) {
                couponLabel = "最高获" + evaluationTask.getCouponAmount() + "元优惠券";
            }
        }

        // 2.保存到需求大厅
        TaskHall taskHall = TaskHall.builder()
                .taskNumber(evaluationTask.getTaskNumber())
                .taskName(evaluationTask.getSubject())
                .taskPrice(price)
                .taskType("评测需求")
                .taskState(taskState)
                .taskStatus(taskStatus)
                // .taskKeyword(goods.getGoodsTag())
                .taskKeyword(evaluationTask.getLabel())
                .taskUser("")
                .taskAuthor(evaluationTask.getInitiatorId())
                .taskCurrentId(evaluationTask.getId())
                .taskHistoryId(evaluationTask.getId())
                .sceneId(evaluationTask.getSceneId())
                .privateId(evaluationTask.getSceneAssetsId())
                .taskLabel("品牌推广报酬")
                .taskColor("#fa5650")
                .taskUrl("/pages_private_scene1/evaluation/sign_up?docUnid=" + evaluationTask.getId())
                .createUser(evaluationTask.getInitiatorId())
                .createUserName(evaluationTask.getInitiatorName())
                .imageUrl(imageUrl)
                .collectType("market")
                .couponLabel(couponLabel)
                .build();
        if (!taskHallService.insert(taskHall)) {
            return AjaxResult.error("保存到需求大厅出错了！");
        }

        // 3.汇集数据（用于企业动态的展示）
        /* 发起品牌推广
        文案：我刚发布了一个新活动，快来跟我一起组队吧。
        图片：活动首图；标题：活动标题；小字：商品/样品规格；
        品牌推广：金额+标签“品牌推广报酬”
        样品推广：金额+标签“样品推广价”*/
        BehavioralData behavioralData = new BehavioralData();
        behavioralData.setTitle("我刚发布了一个新活动，快来跟我一起组队吧。");// 文案
        behavioralData.setSubject(evaluationTask.getSubject());// 标题
        behavioralData.setContent(evaluationTask.getSpecification());// 内容（商品/样品规格）
        // 图片
        if(StrUtil.isNotBlank(evaluationTask.getMainPicture())){
            behavioralData.setImage(evaluationTask.getMainPicture());
        } else {
            if(StrUtil.isNotBlank(evaluationTask.getGoodsImages())){
                behavioralData.setImage(evaluationTask.getGoodsImages().split(",")[0]);
            }
        }
        behavioralData.setPrice(String.valueOf(maxPrice));
        behavioralData.setLabel("品牌推广报酬");
        behavioralData.setType("0");// 类型。0动态；1工作；2商品；3创作
        behavioralData.setJumpUrl("/pages_private_scene1/evaluation/sign_up?docUnid=" + evaluationTask.getId());// 跳转测评报名页面
        behavioralData.setSourceId(evaluationTask.getId());
        behavioralData.setSourceType("1");// 来源类型。0团购；1测评；2样品；3招聘；4协作；5上架商品；6发布学习
        behavioralData.setUserId(evaluationTask.getInitiatorId());
        behavioralData.setUserName(evaluationTask.getInitiatorName());
        behavioralData.setAvatarUrl(evaluationTask.getAvatarUrl());
        behavioralData.setCreateTime(DateUtil.now());
        behavioralData.setUpdateTime(DateUtil.now());

        if (!behavioralDataService.save(behavioralData)){
            return AjaxResult.error("发布测评行为汇集出错了！");
        }

        return AjaxResult.success("发布成功", evaluationTask);
    }

    /**
     * 获取任务详情
     * @param id
     * @return
     */
    @Override
    public EvaluationTask info(String id) {
        EvaluationTask evaluationTask = getById(id);
        if(BeanUtil.isNotEmpty(evaluationTask)){
            // 计算剩余名额
            Long joinQuota = evaluationSignupService.countQuota(new LambdaQueryWrapper<EvaluationSignup>()
                    .eq(EvaluationSignup::getMainId, evaluationTask.getId())
                    .notIn(EvaluationSignup::getStatus, "超时回收", "已回收"));
            evaluationTask.setRemainQuota((int) (evaluationTask.getQuota() - joinQuota));
        }
        return evaluationTask;
    }

    /**
     * 根据订单id获取任务详情
     * @param orderId
     * @return
     */
    @Override
    public EvaluationTask getInfoByOrderId(String orderId) {
        if(StrUtil.isNotBlank(orderId)){
            LambdaQueryWrapper<EvaluationTask> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(EvaluationTask::getOrderId, orderId);
            return getOne(wrapper);
        }
        return null;
    }

    @Override
    public void edit(EvaluationTask evaluationTask) {
        baseMapper.updateById(evaluationTask);
    }

    /**
     * 获取新的id
     * @return
     */
    @Override
    public String getNewId() {
        return String.valueOf(worker.nextId());
    }

    /**
     * 获取测评任务列表
     * 我发起的、我参与的
     * @param vo
     * @return
     */
    @Override
    public List<?> selectList(EvaluationTaskVo vo) {

        if(StrUtil.isBlank(vo.getUserId())){
            throw new ServiceException("用户id不能为空！");
        }

        // 查询类型。publish:我发起的；join:我的测评(我加入的)；不传则默认获取我发起的
        if(StrUtil.isBlank(vo.getType()) || "publish".equals(vo.getType())){
            // 获取我发起的测评任务
            LambdaQueryWrapper<EvaluationTask> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(EvaluationTask::getInitiatorId, vo.getUserId());

            if (StrUtil.isNotBlank(vo.getSearchStr())) {
                wrapper.and(wrap -> wrap.like(EvaluationTask::getSubject, vo.getSearchStr())
                        .or().like(EvaluationTask::getLabel, vo.getSearchStr())
                        .or().like(EvaluationTask::getId, vo.getSearchStr())
                        .or().like(EvaluationTask::getGoodsTag, vo.getSearchStr()));
            }
            wrapper.orderByDesc(EvaluationTask::getCreateTime);
            return list(wrapper);

        } else if("join".equals(vo.getType())){
            // 获取我参与的测评任务
            MPJLambdaWrapper<EvaluationSignup> wrapper2 = new MPJLambdaWrapper<EvaluationSignup>()
                    .selectAll(EvaluationSignup.class)
                    .leftJoin(EvaluationTask.class, EvaluationTask::getId, EvaluationSignup::getMainId)
                    .eq(EvaluationSignup::getPartnerId, vo.getUserId());
            if(StrUtil.isNotBlank(vo.getJoinStatus())){
                wrapper2.eq(EvaluationSignup::getStatus, vo.getJoinStatus());
            } else {
                // 默认获取已验收的
                wrapper2.eq(EvaluationSignup::getStatus, "已验收");
            }
            if (StrUtil.isNotBlank(vo.getSearchStr())) {
                wrapper2.and(wrap -> wrap.like(EvaluationTask::getSubject, vo.getSearchStr())
                        .or().like(EvaluationTask::getLabel, vo.getSearchStr())
                        .or().like(EvaluationTask::getId, vo.getSearchStr())
                        .or().like(EvaluationTask::getGoodsTag, vo.getSearchStr()));
            }
            wrapper2.orderByDesc(EvaluationSignup::getCreateTime);
            return evaluationSignupService.list(wrapper2);
        } else {
            throw new ServiceException("获取不到数据，请检查type参数！");
        }

        // return null;
    }

    /**
     * 获取所有测评任务列表
     * @param vo
     * @return
     */
    @Override
    public List<EvaluationTask> queryAll(EvaluationTaskVo vo) {
        // 获取我发起的测评任务
        LambdaQueryWrapper<EvaluationTask> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(vo.getSearchStr())) {
            wrapper.and(wrap -> wrap.like(EvaluationTask::getSubject, vo.getSearchStr())
                    .or().like(EvaluationTask::getLabel, vo.getSearchStr())
                    .or().like(EvaluationTask::getId, vo.getSearchStr())
                    .or().like(EvaluationTask::getGoodsTag, vo.getSearchStr()));
        }
        wrapper.orderByDesc(EvaluationTask::getCreateTime);
        return list(wrapper);
    }

    /**
     * 活动作废
     * @param vo
     * @return
     */
    @Override
    public boolean finish(EvaluationTaskVo vo) {

        if(StrUtil.isBlank(vo.getId())){
            throw new ServiceException("获取不到参数！");
        }

        EvaluationTask task = getById(vo.getId());
        if(BeanUtil.isEmpty(task)){
            throw new ServiceException("获取不到测评活动！");
        }

        // 任务状态。0:正常结束(到期自动结束)；1:正在进行中；2:报名结束；3:活动作废(手动结束)
        if("0".equals(task.getTaskStatus())){
            throw new ServiceException("活动已结束！");
        } else if("3".equals(task.getTaskStatus())){
            throw new ServiceException("活动已作废，请勿重复操作！");
        }

        /* 不发放评级待办
        // 是否评级发放报酬。0:否；1:是
        if("1".equals(task.getEnableRating())){

            // 评级人头像
            JSONObject userObj = getUserData(task.getRatingMemberId());
            String prvUserAvatar = "";
            if(ObjectUtil.isNotNull(userObj)){
                prvUserAvatar = userObj.getString("avatar");
            }

            // 1.2 给评级人员发送【评级】待办
            Todo todo = Todo.builder()
                    .taskId(Convert.toStr(task.getId()))
                    .subject(task.getSubject())
                    .reqNumber(task.getTaskNumber())
                    .userId(task.getRatingMemberId())
                    .startTime(DateUtil.now())
                    .status("Current")
                    .nodeName("评级")
                    .prvUserId(task.getRatingMemberId())
                    .prvNickName(task.getRatingMemberName())
                    .prvUserAvatar(prvUserAvatar)
                    .minAppUri("/pages_private_scene1/evaluation/rating?docUnid="+ task.getId())// （链接到【评级页面】）
                    .minDoneUrl("/pages_private_scene1/evaluation/ranking_list?docUnid="+ task.getId())// （链接到【排行榜页面】）
                    .build();
            if(!todoService.addToDoData(todo)){
                throw new ServiceException("给评级人员发送【评级】待办出错了！");
            }

            // 1.3 给评级人员发送【评级】通知
            AsyncManager.me().execute(sendMsgService.rating(task));
        }*/

        // 1.4 修改任务状态
        LambdaUpdateWrapper<EvaluationTask> taskUpdateWrapper = new LambdaUpdateWrapper<>();
        taskUpdateWrapper.eq(EvaluationTask::getId, task.getId());
        taskUpdateWrapper.set(EvaluationTask::getTaskStatus, "3");// 任务状态。0:结束；1:正在进行中；2:报名结束；3:活动作废(手动结束)
        if(!update(taskUpdateWrapper)){
            throw new ServiceException("修改任务状态出错了！");
        }

        // 1.5 作废正在进行的报名记录（待提交/待验收）
        if(!taskCancellation(task.getId())){
            throw new ServiceException("作废正在进行的报名记录出错了！");
        }

        // 1.6 从需求大厅下架测评任务
        LambdaUpdateWrapper<TaskHall> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(TaskHall::getTaskCurrentId, task.getId());
        updateWrapper.set(TaskHall::getTaskState, "需求下架");
        updateWrapper.set(TaskHall::getTaskStatus, "下架");
        if(!taskHallService.update(updateWrapper)){
            throw new ServiceException("需求下架出错了！");
        }

        return true;
    }

    /**
     * 活动结束报名
     * @param vo
     * @return
     */
    @Override
    public boolean endJoin(EvaluationTaskVo vo) {

        if(StrUtil.isBlank(vo.getId())){
            throw new ServiceException("获取不到参数！");
        }

        EvaluationTask task = getById(vo.getId());
        if(BeanUtil.isEmpty(task)){
            throw new ServiceException("获取不到测评活动！");
        }

        // 任务状态。0:正常结束(到期自动结束)；1:正在进行中；2:报名结束；3:活动作废(手动结束)
        if("0".equals(task.getTaskStatus())){
            throw new ServiceException("活动已结束！");
        } else if("2".equals(task.getTaskStatus())){
            throw new ServiceException("活动已结束报名，请勿重复操作！");
        } else if("3".equals(task.getTaskStatus())){
            throw new ServiceException("活动已作废！");
        }

        // 修改任务状态
        LambdaUpdateWrapper<EvaluationTask> taskUpdateWrapper = new LambdaUpdateWrapper<>();
        taskUpdateWrapper.eq(EvaluationTask::getId, task.getId());
        taskUpdateWrapper.set(EvaluationTask::getTaskStatus, "2");// 任务状态。0:结束；1:正在进行中；2:报名结束；3:活动作废(手动结束)
        if(!update(taskUpdateWrapper)){
            throw new ServiceException("修改任务状态出错了！");
        }

        return true;
    }

    /**
     * 任务作废（结束所有正在进行的报名记录）
     * 包含以下情况：
     *  1.已报名未提交成果
     *  2.已提交成果未验收
     *  3.退回返修
     * 已验收的不用处理
     * @param id
     * @return
     */
    private boolean taskCancellation(String id){
        // 1. 获取正在进行的报名记录（待提交/已退回/待验收）
        LambdaQueryWrapper<EvaluationSignup> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EvaluationSignup::getMainId, id);
        wrapper.in(EvaluationSignup::getStatus, "待提交", "已退回", "待验收");
        wrapper.orderByDesc(EvaluationSignup::getCreateTime);
        List<EvaluationSignup> signups = evaluationSignupService.list(wrapper);
        for (EvaluationSignup signupInfo : signups){
            // 2. 结束待办（已作废）
            LambdaUpdateWrapper<Todo> todoUpdateWrapper = new LambdaUpdateWrapper<>();
            todoUpdateWrapper.eq(Todo::getTaskId, signupInfo.getId());
            todoUpdateWrapper.eq(Todo::getStatus, "Current");
            todoUpdateWrapper.set(Todo::getStatus, "ARC");
            todoUpdateWrapper.set(Todo::getNodeName, "已作废");
            todoUpdateWrapper.set(Todo::getEndTime, DateUtil.now());
            if(!todoService.update(todoUpdateWrapper)){
                throw new ServiceException("结束待办出错了！");
            }

            // 3. 更新报名记录状态为“已作废”
            LambdaUpdateWrapper<EvaluationSignup> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(EvaluationSignup::getId, signupInfo.getId());
            updateWrapper.set(EvaluationSignup::getStatus, "已作废");
            if(!evaluationSignupService.update(updateWrapper)){
                throw new ServiceException("更新报名记录信息出错了！");
            }
        }
        return true;
    }

    /**
     * 获取用户信息
     * @param userId
     * @return
     */
    private JSONObject getUserData(String userId) {
        JSONObject wxObject = new JSONObject();
        String result = HttpUtil.get(ssoUri + "/user/cache/" + userId);
        if (StrUtil.isNotBlank(result)) {
            wxObject = JSON.parseObject(result);
        }
        if (ObjectUtil.isNull(wxObject.getJSONObject("data"))) {
            return null;
        }
        return wxObject.getJSONObject("data");
    }

    /**
     * 结束待办（提交成果/验收成果）
     * @param signupInfo
     */
    private boolean endSignUpTaskTodo(EvaluationSignup signupInfo){

        /*LambdaUpdateWrapper<Todo> todoUpdateWrapper = new LambdaUpdateWrapper<>();
            todoUpdateWrapper.eq(Todo::getTaskId, signupInfo.getId());
            todoUpdateWrapper.set(Todo::getStatus, "ARC");
            todoUpdateWrapper.set(Todo::getEndTime, DateUtil.now());
            if(!todoService.update(todoUpdateWrapper)){
                throw new ServiceException("结束参与者【提交成果】待办出错了！");
            }*/

        // 情况1：结束参与者【提交成果】待办已报名未提交成果
        if("待提交".equals(signupInfo.getStatus())){
            if(!evaluationSignupService.endTodo(signupInfo.getId(), signupInfo.getPartnerId(), "提交成果", "已作废", "ARC")){
                throw new ServiceException("结束参与者【提交成果】待办出错了！");
            }
        }

        // 情况2：结束参与者【提交成果】待办
        if("待提交".equals(signupInfo.getStatus())){

            // 获取当前节点名称
            String nodeNameSubmit = evaluationSignupService.getCurrentNodeName(signupInfo, "submit");

            // 获取当前的【已办】节点名称
            String doneNodeNameSubmit = evaluationSignupService.getDoneNodeName(signupInfo, "submit");

            if(!evaluationSignupService.endTodo(signupInfo.getId(), signupInfo.getPartnerId(), nodeNameSubmit, doneNodeNameSubmit, "ARC")){
                throw new ServiceException("结束参与者【提交成果】待办出错了！");
            }
        }

        // 情况2：结束验收人【验收成果】待办
        if("待验收".equals(signupInfo.getStatus())){

            // 获取当前节点名称
            String nodeNameAccept = evaluationSignupService.getCurrentNodeName(signupInfo, "accept");

            // 获取当前的【已办】节点名称
            String doneNodeNameAccept = evaluationSignupService.getDoneNodeName(signupInfo, "accept");

            if(!evaluationSignupService.endTodo(signupInfo.getId(), signupInfo.getInspectorId(), nodeNameAccept, doneNodeNameAccept, "ARC")){
                throw new ServiceException("结束验收人【验收成果】待办出错了！");
            }
        }

        return true;
    }

    /** ********************************* 以下是定时任务  start ****************************************** */
    /**
     * 活动结束时间到结束测评任务
     * 次日8:20，强制回收所有活动待办（包含返修、发起人验收等待办）。活动自动归档。
     * 每天08:15分执行一次
     * @return
     */
    @Scheduled(cron = "${evaluation.end_task.cron}")
    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    public boolean endTask(){

        log.info("********************************");
        log.info("开始执行定时任务：活动结束时间到结束测评任务....");

        /**
         * 第1步 获取活动结束时间到结束测评任务
         */
        List<EvaluationTask> taskList = baseMapper.getNeedToEndTask();
        for (EvaluationTask task : taskList){
            /**
             * 第2步 结束测评活动（修改任务状态）
              */
            LambdaUpdateWrapper<EvaluationTask> taskUpdateWrapper = new LambdaUpdateWrapper<>();
            taskUpdateWrapper.eq(EvaluationTask::getId, task.getId());
            taskUpdateWrapper.set(EvaluationTask::getTaskStatus, "0");// 任务状态。0:结束；1:正在进行中；2:报名结束；3:活动作废(手动结束)
            if(!update(taskUpdateWrapper)){
                throw new ServiceException("修改任务状态出错了！");
            }

            /**
             * 第3步 结束正在进行的报名记录（待提交/待验收）
             */
            if(!taskCancellation(task.getId())){
                throw new ServiceException("结束正在进行的报名记录出错了！");
            }
        }

        log.info("执行结束。");
        log.info("********************************");
        return true;
    }

    /**
     * 评级时间到发送评级待办
     * 评级时间的当天8:20给评级人发放评级待办
     * 每天08:20分执行一次
     */
    @Scheduled(cron = "${evaluation.send_rating_todo.cron}")
    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    public boolean sendRatingTodo(){

        log.info("********************************");
        log.info("开始执行定时任务：评级时间到发送评级待办....");

        /**
         * 第1步 获取评级时间到发送评级待办
         */
        List<EvaluationTask> taskList = baseMapper.getNeedToSendatingTodo();
        for (EvaluationTask task : taskList) {
            /**
             * 第2步 发送评级待办
             */
            // 是否评级发放报酬。0:否；1:是
            if ("1".equals(task.getEnableRating())) {

                // 评级人头像
                JSONObject userObj = getUserData(task.getRatingMemberId());
                String prvUserAvatar = "";
                if (ObjectUtil.isNotNull(userObj)) {
                    prvUserAvatar = userObj.getString("avatar");
                }

                // 2.1 给评级人员发送【评级】待办
                Todo todo = Todo.builder()
                        .taskId(Convert.toStr(task.getId()))
                        .subject(task.getSubject())
                        .reqNumber(task.getTaskNumber())
                        .userId(task.getRatingMemberId())
                        .startTime(DateUtil.now())
                        .status("Current")
                        .nodeName("评级")
                        .prvUserId(task.getRatingMemberId())
                        .prvNickName(task.getRatingMemberName())
                        .prvUserAvatar(prvUserAvatar)
                        .minAppUri("/pages_private_scene1/evaluation/rating?docUnid=" + task.getId())// （链接到【评级页面】）
                        .minDoneUrl("/pages_private_scene1/evaluation/ranking_list?docUnid=" + task.getId())// （链接到【排行榜页面】）
                        .build();
                if (!todoService.addToDoData(todo)) {
                    throw new ServiceException("给评级人员发送【评级】待办出错了！");
                }

                /**
                 * 暂时不发送公众号通知（请勿删除）
                 // 2.2 给评级人员发送【评级】通知
                 AsyncManager.me().execute(sendMsgService.rating(task));*/
            }
        }

        log.info("执行结束。");
        log.info("********************************");
        return true;
    }

    /**
     * 测评结束一个月后从需求大厅下架
     * 每天07:50分执行一次
     * @return
     */
    @Scheduled(cron = "${evaluation.off_shelf.cron}")
    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    public void automaticOffShelf_AMonth(){

        log.info("********************************");
        log.info("开始执行定时任务：测评结束一个月后从需求大厅下架....");

        List<EvaluationTask> list = baseMapper.getEndAMonthTaskList();
        for(EvaluationTask task : list){

            // 再次判断，已发布时间为准，一个月后的测评活动，才需要下架
            LambdaUpdateWrapper<TaskHall> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(TaskHall::getTaskCurrentId, task.getId());
            updateWrapper.apply(" DATE_FORMAT(date_add(create_time, interval 1 month), '%Y-%m-%d') = DATE_FORMAT(now(), '%Y-%m-%d') ");
            updateWrapper.set(TaskHall::getTaskState, "需求下架");
            updateWrapper.set(TaskHall::getTaskStatus, "下架");
            if(!taskHallService.update(updateWrapper)){
                throw new ServiceException("需求下架出错了，出错id=" + task.getId());
            }
        }

        log.info("**************执行结束！******************");
        log.info("********************************");

    }

    /** ********************************* 以上是定时任务  end ****************************************** */

    /**
     * 补全迁移的历史数据
     * 需要补全的字段：
     *  发起人头像：avatarUrl
     *  评级标准：ratingCriteria
     *  推广任务：taskRequirements
     *  推广任务图片：taskRequirementsPicture
     *  验收标准：acceptanceCriteria
     *  验收标准图片：acceptanceCriteriaPicture
     *  商品信息：goodsId、goodsTag、goodsImages、specification
     *  企业信息：enterpriseNo、enterpriseName
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean dealHistoricalData() {

        // 记录测评需求，key:测评需求id；value:测评需求
        HashMap<String, Evaluation> demandMap = new HashMap<>();

        // 记录商品信息，key:商品编号；value:商品信息
        HashMap<String, Goods> goodsMap = new HashMap<>();

        // 需要处理的测评任务数据
        LambdaQueryWrapper<EvaluationTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.ne(EvaluationTask::getEvaluationId, "");
        List<EvaluationTask> list = list(wrapper);

        // 记录测评需求id
        List<String> demandIds = new ArrayList<>();

        // 记录商品id
        List<String> goodsNos = new ArrayList<>();

        for(EvaluationTask task : list){
            demandIds.add(task.getEvaluationId());
            goodsNos.add(task.getGoodsNo());
        }

        // 获取测评需求
        LambdaQueryWrapper<Evaluation> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.in(Evaluation::getId, demandIds);
        List<Evaluation> demandList = evaluationService.list(wrapper1);
        for(Evaluation evaluation : demandList){
            demandMap.put(evaluation.getId(), evaluation);
        }

        // 获取商品信息
        LambdaQueryWrapper<Goods> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.in(Goods::getGoodsNo, goodsNos);
        List<Goods> goodsList = goodsService.list(wrapper2);
        for(Goods goods : goodsList){
            goodsMap.put(String.valueOf(goods.getGoodsNo()), goods);
        }

        // 遍历测评任务补全数据
        for(EvaluationTask task : list){
            LambdaUpdateWrapper<EvaluationTask> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(EvaluationTask::getId, task.getId());

            // 发起人头像
            JSONObject userObj = getUserData(task.getInitiatorId());
            if(ObjectUtil.isNotNull(userObj)){
                updateWrapper.set(EvaluationTask::getAvatarUrl, userObj.getString("avatar"));
            }

            // 测评需求
            Evaluation evaluation = demandMap.get(task.getEvaluationId());
            if(BeanUtil.isNotEmpty(evaluation)){
                updateWrapper.set(EvaluationTask::getLevelARatingCriteria, evaluation.getLevelACriterion());// 评级标准（获取A级）
                updateWrapper.set(EvaluationTask::getLevelBRatingCriteria, evaluation.getLevelBCriterion());// 评级标准（获取B级）
                updateWrapper.set(EvaluationTask::getLevelCRatingCriteria, evaluation.getLevelCCriterion());// 评级标准（获取C级）
                updateWrapper.set(EvaluationTask::getTaskRequirements, evaluation.getRemarks());// 推广任务
                updateWrapper.set(EvaluationTask::getAcceptanceCriteria, evaluation.getRequirements());// 验收标准
            }

            // 商品信息
            Goods goods = goodsMap.get(task.getGoodsNo());
            if(BeanUtil.isNotEmpty(goods)){
                updateWrapper.set(EvaluationTask::getGoodsId, goods.getGoodsId());// 商品id
                updateWrapper.set(EvaluationTask::getGoodsTag, goods.getGoodsTag());// 商品标签
                updateWrapper.set(EvaluationTask::getGoodsImages, goods.getGoodsImages());// 商品图
                updateWrapper.set(EvaluationTask::getSpecification, goods.getSpecification());// 规格
                updateWrapper.set(EvaluationTask::getEnterpriseNo, goods.getEnterpriseNo());// 企业编号
                updateWrapper.set(EvaluationTask::getEnterpriseName, goods.getEnterpriseName());// 企业名称
            }

            if(!update(updateWrapper)){
                throw new ServiceException("更新数据出错了？出错记录：" + task.getId());
            }
        }

        return true;
    }

}
